#ifndef _RECOVER_H_
#define _RECOVER_H_
#include <string.h>
typedef struct Recovery{

  /*Name, used by the runtime to find the recovery routine at a certain point*/
  unsigned long name;

  /*Base addresses of data accessed in the recovery routine*/
  /*These are necessary because we get there and don't know where
    the data are.  We need addresses from when the routine is 
    compiled or registered. We can get stack and global addrs
    statically, but for heap data, we'll need to compute them and
    then pass them in dynamically -- not ideal.*/
  unsigned numVars;
  void **vars;
  void (*recover)(); 

}Recovery;



/*This is a convenience wrapper that matches the name of the public interface that we want*/
#define DINO_TASK_BOUNDARY(x,y,...) DINO_RECOVERY(x,y,__VA_ARGS__)

/*DINO_RECOVERY creates a temporary recovery *, populates it
  with the variables that are used in the recovery routine (pointers to them)
  and then passes the recovery structure to the runtime
*/
#define DINO_RECOVERY(x,y,...) do { \
    Recovery r1; \
    r1.name = x; \
    r1.numVars = y; \
    r1.vars = (void**)calloc(sizeof(void*), y); \
    void *tmp[y] = { __VA_ARGS__ }; \
    memcpy(r1.vars, tmp, y * sizeof(void*)); \
    STORE_EXPLICIT_CHECKPOINT_WITH_RECOVERY(x, &r1); \
} while (0);

/*DINO_BIND_FULL let's the name of the Recovery * be anything*/
#define DINO_BIND_FULL(r,n) n=r->vars[__COUNTER__];

/*DINO_BIND assumes the name of the Recovery * is "r"*/
#define DINO_BIND(n) n=r->vars[__COUNTER__]; 

#endif
/*The deal with these functions is this:

  In the original program, you can demarcate a task boundary with 
  
  DINO_TASK_BOUNDARY(19,3,q,r,s)

  What that says is 

  1)This is the boundary of Task 19.  Task IDs should be unique.
  2)The recovery routine associated with this task accesses 3 pieces of state that
    are going to be stored in the checkpoint
  3)The three pieces of state are q, r, and s

  

  The other side of this interface is DINO_BIND(x).  What that does is get
  a variable back out of a Recovery *, for use in a recovery routine.  The macro
  is positional, meaning the first invocation in a file gets the first variable
  in the recovery *, the second gets the second, and so forth. 

  That means there are some rules to using these

  1)TASK BOUNDARY IDS MUST BE UNIQUE
  2)THERE SHOULD BE ONE INSTANCE OF THE RECOVERY() FUNCTION PER SHARED OBJECT BUILT.

*/ 






